// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.
 * Description: support nand flash driver
 * Author: luojie <luojie6@huawei.com>
 * Create: 2019-11-06
 */

#ifndef HIFMC_H
#define HIFMC_H

#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/platform_device.h>
#include "spi_ids.h"

#ifndef CONFIG_FMC_MAX_CHIP
#define CONFIG_FMC_MAX_CHIP                    1
#endif /* CONFIG_FMC_MAX_CHIP */

#define FMC_MTD_TO_HOST(_mtd)               ((struct hifmc_host *)(_mtd))

#define FMC_REG_BASE_ADDRESS_LEN            0x100
#define FMC_BUFFER_BASE_ADDRESS_LEN         (2048 + 128)
#define FMC_FMT_SIZE                        20

#define FMC_CFG               0
#define FMC_ADEDRESS_BITE     3
#define NUMREAD_NUM           8
#define ARRARY_LENGTH         16
#define FMC_ADDRESS_DIG       19
#define SFC_TYPE_FLAG         0x0
#define PARTS_LENGTH          1024
#define FMC_FLAG              0x1
#define PND_PWIDTH_CFG        0xc
#define FMC_CMD               0x24
#define FMC_OP                0x3c
#define FMC_ADDRL             0x2c
#define FMC_ADDRH             0x28
#define FMC_OP_CFG            0x30
#define FMC_FLASH_INFO        0xac
#define FMC_DATA_NUM          0x38
#define FMC_DMA_SADDR_D0      0x4c
#define FMC_DMA_SADDR_OOB     0x5c
#define FMC_DMA_LEN           0x40
#define FMC_OP_CTRL           0x68
#define GLOBAL_CFG            0x4
#define FMC_ECC_CAL           0xe0
#define FMC_DUMMY_MOVE        0xf
#define FMC_CMD_MOVE          0x6
#define FMC_CMD_DATA          0xd8
#define FMC_OP_DATA           0xc1
#define FMC_BIT_THREE         0x3
#define FMC_BIT_FIVE          0x5
#define FMC_BIT_SIX           0x6
#define FMC_BIT_SEVEN         0x7
#define FMC_ADDR              0x85
#define FMC_OP_EN1            0x81
#define FMC_OP_EN2            0xA1
#define FMC_REG_MAX           0xff

#define FMC_BP_MOVE           2
#define FMC_CFG_MOVE          7
#define FMC_BIT_FOUR          4
#define FMC_VALUE_MOVE        11
#define FMC_CMD_READ          16
#define FMC_DMA_EN             1
#define SPIINFO_WRITE_FLAG     0
#define SPIINFO_READ_FLAG      1
#define HIMFC300_PARTITION_HEAD_LEN  2
#define DELAY_TIME           1000
#define NOR_FLASH_ID_MAX       32

#define HIMFC300_TAG_TABLE_MAGIC       0x48695370
#define HIMFC300_READ_CHIPID_MAGIC     0x118417
#define FMC_REG_BASE          0x10a20000
#define FMC_MEM_BASE          0x1c000000
#define FMC_READ_ID_SPI       0x9f
#define FMC_READ_ID_NAND      0x90
#define FMC_CMD_NAND_RESET    0xff

#ifndef CONFIG_HINFC301_PERIPHERY_REGBASE
#define CONFIG_HINFC301_PERIPHERY_REGBASE 0
#endif

/*
 * FMC provides a 9KB (8192byte + 1024byte)
 * on-chip cache to improve the reading speed
 */
#define FMC_DMA_BUFFER_LEN  (8192 + 1024)
#define HIMFC300_MAX_READY_WAIT_JIFFIES      (4000 * HZ)

#define FMC_SIZE_DATA(_n)               ((_n) & 0x3FF)
#define FMC_SIZE_CMD(_n)                ((_n) >> 10)
#define FMC_ECC_BUF(_n)                 (((_n) & 0x7) << 5)
#define FMC_WP_EN                       (1 << 6)
#define FMC_CONFIG_ADDR_MODE            (1 << 1)

struct hifmc_spi {
	char *name;
	/* Write protection BP bit mask, default configuration is 0x07 */
	unsigned char BP_bitmask;
	unsigned int erasesize; /* erase size for the device */
	unsigned long long chipsize; /* size of chip selection */
	int  chipselect; /* chip size */
	void __iomem *iobase; /* io base address */

	unsigned int addrcycle;

	struct spi_operation  read[1]; /* spi read opertaion */
	struct spi_operation  write[1]; /* spi write opertation */
	struct spi_operation  erase[MAX_SPI_OP]; /* spi erase opertation */
};

struct hifmc_host {
	struct mtd_info mtd[1];
	void __iomem *iobase; /* io base address */
	void __iomem *regbase; /* reg base address */
	void __iomem *cfgreg; /* configuration register base address */
	struct device *dev;
	struct mutex lock;
	char *buffer;
	int add_partition; /* partition of controller */
	int num_chip; /* Number of slices supported by the controller */

	unsigned int dma_buffer;
	unsigned int dma_buffer_size;
	unsigned int start_cs; /* chip selection */
	unsigned int start_spi; /* SPI bus */
	struct hifmc_spi spi[CONFIG_FMC_MAX_CHIP+1];

	int (*suspend)(struct platform_device *pltdev, pm_message_t state);
	int (*resume)(struct platform_device *pltdev);
};

int hifmc_spinor_module_init(void);
void hifmc_spinor_module_exit(void);
unsigned int hifmc_protect_get(unsigned int *wp);
unsigned int hifmc_protect_set(unsigned int wp);

#endif /* HIFMC_H */
